import datetime
import enum
import multiprocessing
import os
import subprocess
import sys


@enum.unique
class Host(enum.Enum):
    Darwin = 'darwin'
    Linux = 'linux'

def get_default_host():
    if sys.platform.startswith('linux'):
        return Host.Linux
    elif sys.platform.startswith('darwin'):
        return Host.Darwin
    else:
        raise RuntimeError('Unsupported host: {}'.format(sys.platform))

def build_python(host, python_src, build_dir, install_dir):
    sys.stdout.flush()

    os.makedirs(build_dir, exist_ok=True)
    os.makedirs(install_dir, exist_ok=True)

    cflags = ['-Wno-unused-command-line-argument']
    ldflags = ['-s']
    config_cmd = [
        os.path.join(python_src, 'configure'),
        '--prefix={}'.format(install_dir),
        '--enable-shared',
        '--with-ensurepip=install',
    ]
    env = dict(os.environ)
    if host == Host.Darwin:
        sdkroot = env.get('SDKROOT')
        if sdkroot:
            config_cmd.append('--enable-universalsdk={}'.format(sdkroot))
        else:
            config_cmd.append('--enable-universalsdk')
        config_cmd.append('--with-universal-archs=universal2')

        MAC_MIN_VERSION = '10.14'
        cflags.append('-mmacosx-version-min={}'.format(MAC_MIN_VERSION))
        cflags.append('-DMACOSX_DEPLOYMENT_TARGET={}'.format(MAC_MIN_VERSION))
        cflags.extend(['-arch', 'arm64'])
        cflags.extend(['-arch', 'x86_64'])
        env['MACOSX_DEPLOYMENT_TARGET'] = MAC_MIN_VERSION
        ldflags.append("-Wl,-rpath,'@loader_path/../lib'")
        cflags.append('-Werror=unguarded-availability')
        cflags.append('-DHAVE_DYLD_SHARED_CACHE_CONTAINS_PATH=1')
    elif host == Host.Linux:
        ldflags.append("-Wl,-rpath,\\$$ORIGIN/../lib")
        ldflags.append('-Wl,--as-needed')

    config_cmd.append('CFLAGS={}'.format(' '.join(cflags)))
    config_cmd.append('LDFLAGS={}'.format(' '.join(cflags + ldflags)))

    subprocess.check_call(config_cmd, cwd=build_dir, env=env)

    if host == Host.Darwin:
        libpython = 'libpython3.11.dylib'
        subprocess.check_call(['make',
                               '-j{}'.format(multiprocessing.cpu_count()),
                               libpython],
                              cwd=build_dir)
        subprocess.check_call(['install_name_tool', '-id', '@rpath/' + libpython,
                               libpython], cwd=build_dir)

    subprocess.check_call(['make',
                           '-j{}'.format(multiprocessing.cpu_count()),
                           'install'],
                          cwd=build_dir)
    return (build_dir, install_dir)

def package_python(host, install_dir, dest_dir):
    current_date = datetime.datetime.now().strftime('%Y%m%d')
    if host == Host.Linux:
        package_name = 'python-linux-x86-3.11.4_{}.tar.gz'.format(current_date)
    if host == Host.Darwin:
        package_name = 'python-darwin-universal-3.11.4_{}.tar.gz'.format(current_date)
    package_path = os.path.join(dest_dir, package_name)

    os.makedirs(dest_dir, exist_ok=True)
    sys.stdout.flush()

    EXCLUDES = [
      "lib/python*/config-*",
      # EXCLUDE_FROM_LIB
      "*.pyc", "__pycache__", "*.pickle",
      # TEST_DIRS_ONLY
      "test", "tests",
      # TCLTK_DIRS_ONLY
      "tkinter", "turtledemo",
      # IDLE_DIRS_ONLY
      "idlelib",
      # TCLTK_FILES_ONLY
      "turtle.py",
      # BDIST_WININST_FILES_ONLY
      "wininst-*", "bdist_wininst.py",
    ]
    tar_cmd = ['tar']
    for pattern in EXCLUDES:
      tar_cmd.append('--exclude')
      tar_cmd.append(pattern)
    tar_cmd.extend(['-czvf', package_path, '.'])
    subprocess.check_call(tar_cmd, cwd=install_dir)
def main():
    host = get_default_host()
    python_src = "/home/OpenHarmony/master/third_party/python/"
    out_dir = python_src + "python3out"
    if not os.path.exists(out_dir):
        os.mkdir(out_dir)
    dest_dir = out_dir + "/artifact"

    build_dir = os.path.join(out_dir, 'build')

    if host == Host.Linux:
        install_name = "install/linux-x86/3.11.4"
    if host == Host.Darwin:
        install_name = "install/darwin-x86/3.11.4"
    install_dir = os.path.join(out_dir, install_name)

    build_python(host, python_src, build_dir, install_dir)
    package_python(host, os.path.join(out_dir, "install"), dest_dir)

if __name__ == '__main__':
    main()

